<!-- 
 弹窗管理组件：用来管理弹窗的显示和隐藏

 component：
    :is：弹窗组件
    id：弹窗组件的唯一标识
    v-bind="modal.props" 是 Vue 中的对象绑定语法，它可以将一个对象的所有属性作为 props 批量绑定到一个组件上,等价于 :props="modal.props"
-->
<template>
    <div>
        <component v-for="modal in modals" :is="modal.component" :key="modal.id" v-bind="modal.props"
            @close="handleClose(modal.id, $event)" @ok="handleOk(modal.id, $event)"
            @cancel="handleCancel(modal.id, $event)" />
    </div>
</template>

<script setup>
import { markRaw, ref } from 'vue';



//定义一个弹窗列表，同于存储弹窗组件
const modals = ref([])

//监听弹窗组件的关闭事件
const handleClose = (id, result) => {
    _finish(id, result, 'close');
}

//监听弹窗组件的确定事件
const handleOk = (id, result) => {
    _finish(id, result, 'ok');
}

//监听弹窗组件的取消事件
const handleCancel = (id, result) => {
    _finish(id, result, 'cancel');
}

//处理弹窗组件的关闭、确定、取消事件
const _finish = (id, result, type) => {
    const idx = modals.value.findIndex(m => m.id === id);//找到弹窗组件在列表中的索引
    if (idx !== -1) {//如果找到
        const modal = modals.value[idx];//获取弹窗组件
        modals.value.splice(idx, 1);//从列表中删除弹窗组件
        if (type === 'ok') modal.resolve(result);//如果点击确定，则调用resolve方法
        else if (type === 'cancel') modal.reject(result);//如果点击取消，则调用reject方法
        else modal.reject(result);//如果点击关闭，则调用reject方法
    }
};

//用于打开一个弹窗，传入弹窗类型和对应的参数，他会返回一个promise对象，用于处理弹窗的关闭、确定、取消事件

//这些处理弹窗的事件在_finish方法中处理，需要我们自己实现方法: open().then(res=>{}).catch(err=>{})
const open=(component, props = {})=> {
    console.log('打开弹窗3')
  return new Promise((resolve, reject) => {
    const id = Date.now() + Math.random(); // 生成唯一 id
    modals.value.push({//将弹窗组件添加到弹窗列表中
      id,
      component:markRaw(component), // 要渲染的弹窗组件
      props: {
        ...props,
        visible: true // 默认弹窗可见
      },
      resolve, // Promise 的 resolve 方法
      reject   // Promise 的 reject 方法
    });
  });
}

defineExpose({ open }); //导出open方法
</script>
<style scoped lang="scss"></style>
